package com.inetools.gwetons.client.logging;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptException;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
import com.inetools.gwetons.shared.logging.LogUtil;
import com.inetools.gwetons.shared.logging.LogUtilFactory;
import com.inetools.gwetons.shared.logging.LogUtilFactoryInstanceHolder;
import com.inetools.gwetons.shared.logging.LogUtilFactoryIntf;

public class JsniLogUtilFactory extends LogUtilFactory implements JsniLogUtilFactoryInterface {
	private static JsniLogUtilGinjector jsniLogUtilGinjector;
		public static JsniLogUtilGinjector getJsniLogUtilGinjector() {
			if ( JsniLogUtilFactory.jsniLogUtilGinjector == null) {
				if ( GWT.isClient()) {
					JsniLogUtilGinjector jsniLogUtilGinjectorObj = GWT.create( JsniLogUtilGinjector.class);
					JsniLogUtilFactory.setJsniLogUtilGinjector( jsniLogUtilGinjectorObj);
				}
			}
			return JsniLogUtilFactory.jsniLogUtilGinjector;
		}
		public static void setJsniLogUtilGinjector(
				JsniLogUtilGinjector jsniLogUtilGinjector) {
			JsniLogUtilFactory.jsniLogUtilGinjector = jsniLogUtilGinjector;
		}
	
	static String getLoggerName() {
		return JsniLogUtilFactory.class.getName();
	}
	private static JsniLogUtil getThisJsniLogUtil() {
		LogUtil logUtilObj = LogUtilFactoryInstanceHolder.getLogutilfactory().getLogUtil( getLoggerName());
		
		JsniLogUtil jsniLogUtil = getJsniLogUtilGinjector().getJsniLogUtil();
			jsniLogUtil.setLogUtil( logUtilObj);
		
		return jsniLogUtil;
	}
	
	@Deprecated
	protected static native JsArray<JavaScriptObject> nativeGetLogUtilFunctions( LogUtil logUtilObj) 
	throws JavaScriptException /*-{
		// Just logging preparation ---------------------------------------------------------------
		var methodName = "nativeGetLogUtilFunctions JSNI";
		var thisJsniLogUtil = @com.inetools.gwetons.client.logging.JsniLogUtilFactory::getThisJsniLogUtil()();
		var enteringFunction
		= thisJsniLogUtil.@com.inetools.gwetons.client.logging.JsniLogUtil::getEnteringFunction()();
		var logFunction
		= thisJsniLogUtil.@com.inetools.gwetons.client.logging.JsniLogUtil::getLogFunction()();
		var exitingWithResultFunction
		= thisJsniLogUtil.@com.inetools.gwetons.client.logging.JsniLogUtil::getExitingWithResultFunction()();
		// ----------------------------------------------------------------------------------------
		
		enteringFunction( methodName, [ "logUtilObj(=" + String( logUtilObj) + ")"]);
			
		var functionArray = new Array();
		
		var logMethodReferrer 
		= function( levelObj, message) {
			if ( typeof( levelObj) == "string") {
				logUtilObj.@com.inetools.gwetons.shared.logging.LogUtil::log(Ljava/lang/String;Ljava/lang/String;)(
					levelObj, message);
			}
			else {
				logUtilObj.@com.inetools.gwetons.shared.logging.LogUtil::log(Ljava/util/logging/Level;Ljava/lang/String;)(
					levelObj, message);
			}
		};
		functionArray.push( logMethodReferrer);
	
		var jsniLogUtilObj 
		= @com.inetools.gwetons.client.logging.JsniLogUtilFactory::getJsniLogUtil(Lcom/inetools/gwetons/client/logging/JsniLogUtil;Lcom/inetools/gwetons/shared/logging/LogUtil;Ljava/lang/String;Lcom/inetools/gwetons/client/logging/JsniLogUtilFactoryInterface;)(
			null, logUtilObj, logUtilObj.@com.inetools.gwetons.shared.logging.LogUtil::getLoggerName(), null);
		var logEnteringMethodReferrer 
		= function( strArray) {
			jsniLogUtilObj.@com.inetools.gwetons.client.logging.JsniLogUtil::logEntering(Lcom/google/gwt/core/client/JsArrayString;)(
				strArray);
		};
		functionArray.push( logEnteringMethodReferrer);
		
		var logExitingMethodReferrer 
		= function( strArray) {
			jsniLogUtilObj.@com.inetools.gwetons.client.logging.JsniLogUtil::logExiting(Lcom/google/gwt/core/client/JsArrayString;)(
				strArray);
		};
		functionArray.push( logExitingMethodReferrer);
		
		logFunction( 
			@java.util.logging.Level::FINEST, 
			"Returning array of 3 functions refering to log method, logEntering method and "
			+ "logExiting method of logUtilObj(=" + String( logUtilObj) + ")."
			);
		exitingWithResultFunction( methodName, String( functionArray));
		return functionArray;
	}-*/;

	@Deprecated
	protected static native JsArray<JavaScriptObject> nativeGetDummyFunctions() /*-{
		// Just logging preparation ---------------------------------------------------------------
		var methodName = "nativeGetDummyFunctions";
		var enteringFunction
		= thisJsniLogUtil.@com.inetools.gwetons.client.logging.JsniLogUtil::getEnteringFunction()();
		var exitingWithResultFunction
		= thisJsniLogUtil.@com.inetools.gwetons.client.logging.JsniLogUtil::getExitingWithResultFunction()();
		// ----------------------------------------------------------------------------------------
	
		enteringFunction( methodName, null);
	
		var functionArray = new Array();
			var dummyFunction = function() {};
			for ( var index = 0; index < 3; index++) {
				functionArray.push( dummyFunction);
			} // for
	
		exitingWithResultFunction( methodName, String( functionArray));
		return functionArray;
	}-*/;

	protected JsniLogUtilFactory() {
	}
	
	public static JsniLogUtil getJsniLogUtil( 
			JsniLogUtil instance, LogUtil logUtil, 
			String loggerName, JsniLogUtilFactoryInterface jsniLogUtilFactory) {
		String methodName = "getJsniLogUtil";
		LogUtil thisLogUtil = JsniLogUtilFactory.getThisJsniLogUtil().getLogUtil();
		thisLogUtil.entering( 
				methodName, 
				new Object[]{ instance, logUtil, loggerName, jsniLogUtilFactory}
				);
		
		if ( instance != null) {
			thisLogUtil.exiting( methodName, instance);
			return instance;
		}
		
		JsniLogUtilFactoryInterface jsniLogUtilFactoryObj = jsniLogUtilFactory;
			if ( jsniLogUtilFactoryObj == null) {
				jsniLogUtilFactoryObj = JsniLogUtilFactoryInstanceHolder.getJsniLogutilFactory();
			}
		LogUtil logUtilObj = logUtil;
			if ( logUtilObj == null) {
				logUtilObj = jsniLogUtilFactoryObj.getLogUtil( loggerName);
			}
		JsniLogUtil jsniLogUtilObj = jsniLogUtilFactoryObj.getJsniLogUtil( logUtilObj);
		
		thisLogUtil.exiting( methodName, jsniLogUtilObj);
		return jsniLogUtilObj;
	}
	
	
	@Deprecated
	public static JsArray<JavaScriptObject> getLogUtilFunctions( 
			LogUtil instance, String loggerName, LogUtilFactoryIntf factoryInstance) {
		
		String methodName = "getLogUtilFunctions";
		LogUtil thisLogUtil = JsniLogUtilFactory.getThisJsniLogUtil().getLogUtil();
		thisLogUtil.logEntering(
				methodName,
				"with arguments of instance(=" + ((instance == null) ? "null" : instance.toString())
				+ "), loggerName(=" + ((loggerName == null) ? "null" : loggerName)
				+ "), factoryInstance(=" + ((factoryInstance == null) ? "null" : factoryInstance.toString())
				+ ")"
				);
	
		LogUtil logUtilObj = instance;
			if ( logUtilObj == null) {
				LogUtilFactoryIntf logUtilFactoryObj = factoryInstance;
					if ( logUtilFactoryObj == null) {
						logUtilFactoryObj = LogUtilFactoryInstanceHolder.getLogutilfactory();
					}
				logUtilObj = logUtilFactoryObj.getLogUtil( loggerName);
			}
		JsArray<JavaScriptObject> jsFunctionArray 
		= JsniLogUtilFactory.nativeGetLogUtilFunctions( logUtilObj);
		
		thisLogUtil.logExiting( methodName, jsFunctionArray);
		return jsFunctionArray;
	}
	
	// JsniLogUtilFactoryInterface methods --------------------------------------------------------
	@Override
	public JsniLogUtil getJsniLogUtil( LogUtil logUtil) {
		String methodName = "getJsniLogUtil";
		LogUtil thisLogUtil = JsniLogUtilFactory.getThisJsniLogUtil().getLogUtil();
		thisLogUtil.entering( methodName, new Object[]{ logUtil});
		
		JsniLogUtil jsniLogUtil = JsniLogUtilFactory.getJsniLogUtilGinjector().getJsniLogUtil();
			jsniLogUtil.setLogUtil( logUtil);
		
		thisLogUtil.exiting( methodName, jsniLogUtil);
		return jsniLogUtil;
	}
	
	@Override
	public JsniLogUtil getJsniLogUtil( String loggerName) {
		String methodName = "getJsniLogUtil";
		LogUtil thisLogUtil = JsniLogUtilFactory.getThisJsniLogUtil().getLogUtil();
		thisLogUtil.entering( methodName, new Object[]{ loggerName});

		LogUtil logUtil = LogUtilFactory.getLogUtilGinjector().getLogUtil();
			logUtil.setUpLogger( loggerName);
		
		JsniLogUtil jsniLogUtil = getJsniLogUtil( logUtil);

		thisLogUtil.exiting( methodName, jsniLogUtil);
		return jsniLogUtil;
	}
	
	@Deprecated
	@Override
	public JsArray<JavaScriptObject> getLogUtilFunctions( LogUtil logUtil) {
		String methodName = "getLogUtilFunctions";
		LogUtil thisLogUtil = JsniLogUtilFactory.getThisJsniLogUtil().getLogUtil();
		thisLogUtil.logEntering(
				methodName,
				"with argument of logUtil(=" + ((logUtil == null) ? "null" : logUtil.toString()) + ")"
				);

		if (logUtil == null) {
			JsArray<JavaScriptObject> jsFunctionArray = JsniLogUtilFactory.nativeGetDummyFunctions();
			thisLogUtil.logExiting( methodName, jsFunctionArray);
			return jsFunctionArray;
		}

		JsArray<JavaScriptObject> jsFunctionArray = JsniLogUtilFactory.nativeGetLogUtilFunctions( logUtil);
		thisLogUtil.logExiting(methodName, jsFunctionArray);
		return jsFunctionArray;
	}

	@Deprecated
	@Override
	public JsArray<JavaScriptObject> getLogUtilFunctions( String loggerName) {
		String methodName = "getLogUtilFunctions";
		LogUtil thisLogUtil = JsniLogUtilFactory.getThisJsniLogUtil().getLogUtil();
		thisLogUtil.logEntering(
				methodName,
				"with argument of loggerName(=" + ((loggerName == null) ? "null" : loggerName) + ")"
				);

		JsArray<JavaScriptObject> jsFunctionArray;
		if ( loggerName == null) {
			jsFunctionArray = JsniLogUtilFactory.nativeGetDummyFunctions();
		}
		else {
			LogUtil logUtil = getLogUtil( loggerName);
			jsFunctionArray = JsniLogUtilFactory.nativeGetLogUtilFunctions( logUtil);
		}

		thisLogUtil.logExiting( methodName, jsFunctionArray);
		return jsFunctionArray;
	}
	// --------------------------------------------------------------------------------------------
}
